home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
kill_user.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
6KB
|
212 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: kill_user.c,v 1.50 2001/02/15 08:39:45 drscholl Exp $ */
/* Modified 30/05/01 : Added include "extrasocket.h" with inlines for a few
for Amiga port : bsdsocket.library functions not emulated by ixemul
*/
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#ifndef WIN32
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include "opennap.h"
#include "debug.h"
#include "extrasocket.h"
/* send a message to all local mods */
void
notify_mods (unsigned int level, const char *fmt, ...)
{
int len;
va_list ap;
LIST *list;
CONNECTION *con;
va_start (ap, fmt);
vsnprintf (Buf + 4, sizeof (Buf) - 4, fmt, ap);
va_end (ap);
set_tag (Buf, MSG_SERVER_NOSUCH);
len = strlen (Buf + 4);
set_len (Buf, len);
for (list = Mods; list; list = list->next)
{
con = list->data;
if (con->uopt->usermode & level)
queue_data (con, Buf, len + 4);
}
}
/* request to kill (disconnect) a user */
/* [ :<nick> ] <user> [ "<reason>" ] */
HANDLER (kill_user)
{
char *av[2];
int ac = -1;
USER *sender, *user;
char *sender_name;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
if (pkt)
ac = split_line (av, FIELDS (av), pkt);
if (ac < 1)
{
if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH,
"kill failed: too few parameters");
return;
}
user = hash_lookup (Users, av[0]);
if (!user)
{
if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH, "kill failed: no such user");
return;
}
ASSERT (validate_user (user));
/* check for permission */
if (sender && user->level >= sender->level && sender->level < LEVEL_ELITE)
{
if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH,
"kill failed: permission denied");
return;
}
if (ac > 1)
truncate_reason (av[1]);
#define REASON ((ac > 1) ? av[1] : "")
kill_user_internal (con, user, sender_name, sender, "%s", REASON);
}
void
kill_user_internal (CONNECTION * con,
USER * user,
const char *sender_name,
USER * sender, const char *fmt, ...)
{
va_list ap;
char reason[128];
ASSERT (Max_Reason <= (int) sizeof (reason));
va_start (ap, fmt);
vsnprintf (reason, sizeof (reason), fmt, ap);
va_end (ap);
pass_message_args (con, MSG_CLIENT_KILL, ":%s %s \"%s\"",
sender_name, user->nick, reason);
notify_mods (KILLLOG_MODE, "%s%s killed %s: %s",
!sender ? "Server " : "", sender_name, user->nick, reason);
/* forcefully close the client connection if local, otherwise remove
* from global user list
*/
if (ISUSER (user->con))
{
const char *who;
if (sender && sender->cloaked && user->level < LEVEL_MODERATOR)
who = "Operator";
else
who = sender_name;
send_cmd (user->con, MSG_SERVER_NOSUCH,
"You have been killed by%s %s: %s",
!sender ? " server " : "", who, reason);
send_cmd (user->con, MSG_SERVER_DISCONNECTING, "0");
user->con->killed = 1; /* don't generate a QUIT message */
destroy_connection (user->con);
}
else
{
/* user is on remote server */
hash_remove (Users, user->nick);
}
}
struct gkilldata
{
char *reason;
USER *sender;
unsigned int ip;
CONNECTION *con;
};
static void
mkill_user_cb (USER * user, struct gkilldata *data)
{
if (user->ip == data->ip)
{
if (data->sender && user->level >= data->sender->level &&
data->sender->level < LEVEL_ELITE)
{
ASSERT (ISUSER (data->sender->con));
send_cmd (data->sender->con, MSG_SERVER_NOSUCH,
"kill failed: permission denied");
return;
}
kill_user_internal (data->sender->con, user, data->sender->nick,
data->sender, "%s", data->reason);
}
}
/* 10122 <ip> ["reason"]
* mass kill by ip address
*/
HANDLER (mass_kill)
{
char *av[2];
int ac;
unsigned int longip;
struct gkilldata data;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
CHECK_USER_CLASS ("mass_kill");
if (con->user->level < LEVEL_MODERATOR)
{
permission_denied (con);
return;
}
ac = split_line (av, FIELDS (av), pkt);
if (ac < 1)
{
unparsable (con);
return;
}
longip = inet_addr (av[0]);
if (longip == (u_int) - 1)
{
if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH,
"kill failed: invalid ip specified %s", av[0]);
return;
}
if (ac > 1)
truncate_reason (av[1]);
data.reason = (ac > 1) ? av[1] : "mkill by ip";
data.ip = longip;
data.sender = con->user;
/* we generate a kill message for each killed user rather than passing
* the mass kill message.
*/
hash_foreach (Users, (hash_callback_t) mkill_user_cb, &data);
}